package com.colin.app.activity.senior.threadpool;

import com.colin.library.help.LogHelp;

import java.util.LinkedList;

/**
 * Created by Colin on 2017/3/3.
 * 自定义线程池
 */

public class MyThreadPool extends ThreadGroup {
    private boolean isClose = false;        //线程池是否关闭
    private LinkedList workQueue;           //工作队列
    private static int threadPollID = 1;    //线程池ID

    public MyThreadPool(String name) {
        super(name);
    }

    public MyThreadPool(ThreadGroup parent, String name) {
        super(parent, name);
    }

    public MyThreadPool(int poolSize) {
        //调用父类构造方法，指定ThreadGroup的名称
        super("threadPoolId" + "");
        //继承的方法，设置是否设置守护线程池
        setDaemon(true);
        //创建工作队列
        workQueue = new LinkedList();
        for (int i = 0; i < poolSize; i++) {
            //创建并启动工作线程，创建线程池最大容量数的工作线程
            new WorkThread(i).start();
        }
    }

    /**
     * 向工作线程中添加一个任务，由工作线程来执行该任务
     *
     * @param task
     */
    public synchronized void execute(Runnable task) {
        //首先判断线程池是否在工作
        if (isClose) {
            throw new IllegalStateException();
        }
        if (task != null) {
            //向消息队列中添加一个任务
            workQueue.add(task);
            //唤醒一个正在getTask()方法中等待任务的工作线程
            notify();
        }
    }

    /**
     * 从工作队列中取出一个任务，工作线程会调用该方法
     *
     * @param threadId
     * @return
     * @throws InterruptedException
     */
    private synchronized Runnable getTask(int threadId) throws InterruptedException {
        while (workQueue.size() == 0) {
            if (isClose) {
                return null;
            }
            //如果工作线程中没有任务，那么就等待着
            LogHelp.d("工作线程" + threadId + "等待任务");
            wait();
        }
        //返回队列中的第一个元素，并从队列中删除
        LogHelp.d("工作线程" + threadId + "开始执行任务...");
        return (Runnable) workQueue.removeFirst();
    }

    /**
     * 等待工作线程把任务执行完成
     */
    public void waitFinish() {
        synchronized (this) {
            isClose = true;
            //唤醒所有还在getTask()方法中等待任务的工作线程
            notifyAll();
        }
        //activeCount()返回该线程组中活动线程的估计值
        Thread[] threads = new Thread[activeCount()];
        //enumerate方法继承自ThreadGroup，根据活动的线程的估计值获得该线程组中当前所有活动的工作线程
        int count = enumerate(threads);
        //等待所有工作线程结束
        for (int i = 0; i < count; i++) {
            try {
                //等待工作线程结束
                threads[i].join();
            } catch (InterruptedException e) {
                LogHelp.e(e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭线程池
     */

    public synchronized void closePool() {
        if (!isClose) {
            //等待工作线程执行完毕
            waitFinish();
            isClose = true;
            //清空工作队列
            workQueue.clear();
            //中断线程池所有的工作线程
            interrupt();
        }
    }


    //工作线程，负责从工作队列中取出任务，并执行
    private class WorkThread extends Thread {
        private int id;

        public WorkThread(int id) {
            //父类构造，将线程加入到当前ThreadPool线程组
            super(MyThreadPool.this, id + "");
            this.id = id;
        }

        public void run() {
            //继承自Thread，判断线程是否被中断
            while (!isInterrupted()) {
                Runnable task = null;
                try {
                    //取出任务
                    task = getTask(id);
                } catch (InterruptedException e) {
                    LogHelp.e(e.getMessage());
                    e.printStackTrace();
                }
                //如果getTask()返回null或者线程执行getTask()时被中断，则结束此线程
                if (task == null) {
                    return;
                }
                //运行任务
                task.run();
            }


        }
    }
}
